package com.self.common.aspect;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.self.common.constant.CommonConstants;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.UriUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;

/**
 * @version v1.0
 * @ClassName: WebLogAspect
 * @Description:
 * @Author: Mac
 * @Date: 2022/5/29 12:59
 */
@Aspect
@Component
@Order(1)
@Slf4j
public class WebLogAspect {

    @Pointcut("execution(* com.self..controller.*.*(..))")
    public void point(){}

    @Around("point()")
    public Object recordWebLog(ProceedingJoinPoint joinPoint) throws Throwable{
        Object obj = null;
        WebLog webLog = new WebLog();
        long start = System.currentTimeMillis();
        obj = joinPoint.proceed(joinPoint.getArgs());
        long end = System.currentTimeMillis();
        webLog.setSpendTime((int)(end - start)/1000);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String url = request.getRequestURL().toString();
        webLog.setUri(request.getRequestURI());
        webLog.setUrl(url);
        webLog.setIp(request.getRemoteAddr());
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        webLog.setUsername(authentication == null ? CommonConstants.ANONYMOUS:authentication.getPrincipal().toString());
        webLog.setBasePath(StrUtil.removeSuffix(url, URLUtil.url(url).getPath()));
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //目标方法
        Method method = signature.getMethod();
        //获取当前目标对象
        Object target = joinPoint.getTarget();
        webLog.setMethod(target.getClass().getName()+"."+method.getName());
        webLog.setResult(obj);
        //获取@ApiOperation()注解
        ApiOperation annotation = method.getAnnotation(ApiOperation.class);
        webLog.setDescription(annotation == null?"no desc":annotation.value());
        webLog.setParameter(getTargetParams(method,joinPoint.getArgs()));
        log.info("请求的日志:{}", JSONObject.toJSONString(webLog,true));
        return obj;
    }

    public static Object getTargetParams(Method method, Object[] args) {
        HashMap<String, Object> objectHashMap = Maps.newHashMap();
        LocalVariableTableParameterNameDiscoverer parameterName = new LocalVariableTableParameterNameDiscoverer();
        String[] parameterNames = parameterName.getParameterNames(method);
        if (parameterNames != null && parameterNames.length >= 0){
            for (int i = 0 ; i < parameterNames.length ; i++){
                String name = parameterNames[i];
                if ("password".equalsIgnoreCase(name) || "file".equalsIgnoreCase(name)){
                    objectHashMap.put(name,"受限的支持类型") ;
                }else{
                    objectHashMap.put(parameterNames[i],args[i]);
                }
            }
        }
        return objectHashMap;
    }
}
